package com.dizner.androidcartest;

import android.app.Service;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;

import com.google.gson.Gson;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class SocketNetworkService {


    private static final SocketNetworkService ourInstance = new SocketNetworkService();

    private static final String TAG = "SocketNetworkService";

    private Socket socket;

    private TreeMap<Integer, OnMessageListener> listeners;

    static SocketNetworkService getInstance() {
        return ourInstance;
    }


    private SocketNetworkService() {

    }


    public void register(@NonNull OnMessageListener listener) {
        if (listeners == null) {
            listeners = new TreeMap<>();
        }
        listeners.put(listener.hashCode(), listener);
    }

    public void unRegister(@NonNull OnMessageListener listener) {
        if (listeners != null) {
            listeners.remove(listener.hashCode());
        }
    }

    public void startServer() {
        initServer();
    }

    /**
     * 初始化SocketServer
     *
     * @throws IOException
     */
    private void initServer() {

        initBroacastRecover();
//        initBroacast();

        new Thread() {
            @Override
            public void run() {
                ServerSocket server = null;
                while (true) {
                    try {
                        server = new ServerSocket(10201);
//                    server.setSoTimeout(60);
                        Log.i(TAG, "等待连接");
                        socket = server.accept();
                        Log.i(TAG, "连接成功");
                        InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8);
                        BufferedReader reader = new BufferedReader(inputStreamReader);
                        String data = null;
                        while ((data = reader.readLine()) != null) {
                            Log.i(TAG, "收到客户端的数据-----------------------------:" + data);
                            if (!TextUtils.isEmpty(data)) {
                                try {
                                    JSONObject jsonObject = new JSONObject(data);
                                    int msgType = jsonObject.optInt("type");
//                                    String msgBody = jsonObject.optString("body");
                                    Message message = mHandler.obtainMessage();
                                    message.what = msgType;
                                    message.obj = data;
                                    mHandler.sendMessage(message);
                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            Log.i(TAG, "连接断开，重新开始");
                            if (server != null) {
                                server.close();
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        }.start();
    }

    private void initBroacastRecover() {
        try {
            recoverDatagramSocket = new DatagramSocket(1099);
        } catch (Exception e) {
            e.printStackTrace();
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        byte buf[] = new byte[1024];
                        DatagramPacket data = new DatagramPacket(buf, buf.length);
                        recoverDatagramSocket.receive(data);
                        String content = new String(data.getData()).trim();
                        if (TextUtils.equals(content, "START_IP_BROD_CAST")) {
                            initBroacast(data.getAddress().getHostAddress());
                            return;
                        }
                        Log.i(TAG, "-----" + content);
//                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    DatagramSocket sendDatagramSocket = null;
    DatagramSocket recoverDatagramSocket = null;

    private boolean initBroacast(final String targetAddress) {
        final String msg = "CAR_CONTROL_ACCESS";
        if (TextUtils.isEmpty(targetAddress)) {
            return false;
        }

//        Log.i(TAG, "目标地址：-----" + targetAddress);

        try {
            sendDatagramSocket = new DatagramSocket();
            sendDatagramSocket.setBroadcast(true);
        } catch (SocketException e) {
            e.printStackTrace();
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        DatagramPacket data = new DatagramPacket(msg.getBytes(), msg.length(), InetAddress.getByName(targetAddress), 1099);
                        sendDatagramSocket.send(data);
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        return true;

    }

    public void sendMsg(final String msg) {

        if (socket != null && socket.isConnected()) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        PrintWriter output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true);
                        output.write(msg);
                        output.write("\n");
                        socket.getOutputStream().flush();
                        output.flush();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

    }

    private Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case Msg_Type.MSG_CHARACTER:
                    Log.i(TAG, "收到字符消息----:" + msg.obj.toString());
                    requestCallbackByMsg(msg.obj.toString());
                    break;
                case Msg_Type.MSG_CONTROL:
//                    Log.i(TAG, "收到控制消息----:" + msg.obj.toString());
                    requestCallbackByMsg(msg.obj.toString());
                    break;
                case Msg_Type.MSG_SYSTEM:
                    Log.i(TAG, "收到系统消息----:" + msg.obj.toString());
                    requestCallbackByMsg(msg.obj.toString());
                    break;
            }
            return false;
        }
    });


    private void requestCallbackByMsg(String msg) {
        if (listeners != null) {
            Iterator<Map.Entry<Integer, OnMessageListener>> iterator = listeners.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<Integer, OnMessageListener> next = iterator.next();
                if (next.getValue() != null) {
                    convertObj(msg, next.getValue());
                }
            }
        }
    }

    private void requestCallbackByConnect() {
        if (listeners != null) {
            Iterator<Map.Entry<Integer, OnMessageListener>> iterator = listeners.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<Integer, OnMessageListener> next = iterator.next();
                if (next.getValue() != null) {
                    next.getValue().onConnect();
                }
            }
        }
    }

    private void requestCallbackByDisConnect() {
        if (listeners != null) {
            Iterator<Map.Entry<Integer, OnMessageListener>> iterator = listeners.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<Integer, OnMessageListener> next = iterator.next();
                if (next.getValue() != null) {
                    next.getValue().onDisconnect();
                }
            }
        }
    }

    private void convertObj(String str, OnMessageListener value) {
        if (TextUtils.isEmpty(str)) {
            return;
        }
        if (value == null) {
            return;
        }

//        Class<?> aClass = null;
//        for (Method method : value.getClass().getMethods()) {
//            if (TextUtils.equals(method.getName(), "onMessage")) {
//                aClass = method.getParameterTypes()[0];
//                break;
//            }
//        }

        Log.i(TAG, str);


        Gson gson = new Gson();

        value.onMessage(gson.fromJson(str, BaseMessage.class));


    }

    static interface OnMessageListener {
        void onMessage(BaseMessage msg);

        void onConnect();

        void onDisconnect();
    }

    static class Msg_Type {
        final static int MSG_CONTROL = 0x1;//控制消息
        final static int MSG_SYSTEM = 0x2;//系统消息
        final static int MSG_CHARACTER = 0x3;//字符串消息
    }

}
